package com.rpcservice.rpc.remoting.dto;

import lombok.*;

import java.io.Serializable;

/**
 * rpc 请求实体类。当你要调用远程方法的时候，
 * 你需要先传输一个 RpcRequest 给对方，
 * RpcRequest 里面包含了要调用的目标方法和类的名称、参数等数据。
 * 另外，version 字段（服务版本）主要是为后续不兼容升级提供可能。
 * group 字段主要用于处理一个接口有多个类实现的情况。
 */
@AllArgsConstructor
@NoArgsConstructor
@Getter
@Builder
@ToString
public class RpcRequest implements Serializable {
    private static final long serialVersionUID = 1905122041950251208L;

    /**
     * 调用唯一标识。客户端用它把请求和响应配对
     * （通常是 Map<requestId, CompletableFuture<?>>）。
     */
    private String requestId;
    /**
     * 接口全名（如 com.xxx.UserService），用于定位服务。
     */
    private String interfaceName;
    /**
     * 方法名，比如getById
     */
    private String methodName;
    /**
     * 参数值与参数类型。为什么要 paramTypes？因为 Java 支持方法重载，仅靠值在反射时不够精确。
     */
    private Object[] parameters;
    /**
     * 参数类型
     */
    private Class<?>[] paramTypes;
    /**
     * 这帧是什么类型（请求/响应/心跳/异常…），便于 pipeline 分流。
     */
    private RpcMessageType rpcMessageType;
    /**
     * 服务版本,为不兼容升级/灰度做准备。例如老接口升级到 v2 改了签名，提供者和消费者都标注 version="2.0" 才能对上。
     */
    private String version;
    /**
     * 服务分组,为多实现隔离或环境/地域隔离准备。常见用法：
     * 一个接口多个实现：group="algoA" / group="algoB"
     * 运行环境：group="dev"|"test"|"prod"
     * 机房/地域：group="cn-east-1"|"us-west"
     * 你的 toRpcProperties() 把三要素拼成一个服务键：
     * serviceName(=interfaceName) + version + group。
     * 注册/发现一般就按这三元组建路径或索引
     * （例如 ZK：/services/{serviceName}/{group}/{version}/providers/...）
     */
    private String group;

    public String getRpcServiceName() {
        return this.getInterfaceName() + this.getGroup() + this.getVersion();
    }

    /**
     * 什么时候用 version，什么时候用 group？
     * version：接口契约层面有破坏兼容的改动（方法签名/语义变了）。新旧版本可以长期并存，消费者显式选用。
     * group：同一版本但运行维度不同的隔离（实现策略、环境、地域、租户）。通常依赖侧按需路由或通过配置切换。
     */
}
